package com.keyingbo.orm.framework.impl;

import com.keyingbo.orm.framework.IEntityStatement;
import com.keyingbo.orm.framework.support.EntityOperation;
import com.keyingbo.orm.framework.support.Order;
import com.keyingbo.orm.framework.support.ParamMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.core.common.utils.StringUtils;
import javax.sql.DataSource;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Auther: KEYB
 * @Date: 2019-4-28 10:33
 * @Description:
 */
public class EntityStatment<T> implements IEntityStatement<T> , InitializingBean {
    private static final Log log = LogFactory.getLog(EntityStatment.class);



    private Class<T> entityClass;
    private BeanInfo entityBeanInfo;
    private DataSource dataSource;
    private EntityOperation<T> op;

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    private String tableName = "";


    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public T find(Serializable id) {
        String sql = "select " + op.allColumn + " from " + getTableName() + " where " + getPKColumn() + " = ? " ;
        List<T> list = this.getJdbcTemplate().query(sql, this.op.rowMapper,new Object[]{id});
        if (list.size() > 0) return list.get(0);
        return null;
    }

    @Override
    public void create(T t) {
        this.doInsert(parse(t));
    }

    private void doInsert(Map<String, Object> params) {
        String sql = this.makeSimpleInsertSql(this.getTableName(), params);
        int ret = this.getJdbcTemplate().update(sql, params.values().toArray());
    }

    private String makeSimpleInsertSql(String tableName, Map<String, Object> params) {
        if(StringUtils.isEmpty(tableName) || params == null || params.isEmpty()){
            return "";
        }
        StringBuffer sb = new StringBuffer();
        sb.append("insert into ").append(tableName);

        StringBuffer sbKey = new StringBuffer();
        StringBuffer sbValue = new StringBuffer();

        sbKey.append("(");
        sbValue.append("(");
        //添加参数
        Set<String> set = params.keySet();
        int index = 0;
        for (String key : set) {
            sbKey.append(key);
//			sbValue.append(" :").append(key);
            sbValue.append(" ?");
            if(index != set.size() - 1){
                sbKey.append(",");
                sbValue.append(",");
            }
            index++;
        }
        sbKey.append(")");
        sbValue.append(")");

        sb.append(sbKey).append("VALUES").append(sbValue);

        return sb.toString();
    }

    @Override
    public void update(T t) throws Exception{
        op.pkField.setAccessible(true);
        this.doUpdate(op.pkField.get(t), parse(t));
    }

    private void doUpdate(Object pkValue, Map<String, Object> params) {
        String sql = this.makeDefaultSimpleUpdateSql(pkValue, params);
        params.put(this.getPKColumn(), pkValue);
        int ret = getJdbcTemplate().update(sql, params.values().toArray());
    }

    private String makeDefaultSimpleUpdateSql(Object pkValue, Map<String, Object> params) {
        return this.makeSimpleUpdateSql(getTableName(), getPKColumn(), pkValue, params);
    }

    private String makeSimpleUpdateSql(String tableName, String pkColumn, Object pkValue, Map<String, Object> params) {
        if(StringUtils.isEmpty(tableName) || params == null || params.isEmpty()){
            return "";
        }

        StringBuffer sb = new StringBuffer();
        sb.append("update ").append(tableName).append(" set ");
        //添加参数
        Set<String> set = params.keySet();
        int index = 0;
        for (String key : set) {
//			 sb.append(key).append(" = :").append(key);
            sb.append(key).append(" = ?");
            if(index != set.size() - 1){
                sb.append(",");
            }
            index++;
        }
//		sb.append(" where ").append(pkName).append(" = :").append(pkName) ;
        sb.append(" where ").append(pkColumn).append(" = ?");
        params.put("where_" + pkColumn,params.get(pkColumn));

        return sb.toString();
    }

    private String getPKColumn() {
        return op.pkField.getName();
    }

    @Override
    public int delete(T entity) throws Exception {
        op.pkField.setAccessible(true);
        String sql = "delete from " + getTableName() + " where " + getPKColumn() + " = ? " ;
        return this.getJdbcTemplate().update(sql, new Object[]{op.pkField.get(entity)});
    }

    @Override
    public List<T> findBy(ParamMap pm, Order... orders) {
        return null;
    }

    @Override
    public List<T> findBy(ParamMap pm) {
        return null;
    }

    @Override
    public List<T> findAll() {
        String sql = "select " + op.allColumn + " from " + getTableName();
        return this.getJdbcTemplate().query(sql, this.op.rowMapper);
    }

    private JdbcTemplate getJdbcTemplate(){
        return new JdbcTemplate(this.dataSource);
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        this.entityBeanInfo = Introspector.getBeanInfo(this.entityClass, Object.class);
        op = new EntityOperation<T>(entityClass);
        this.setTableName(op.tableName);
    }
    private String getTableName() {
        return tableName;
    }
    public Class<T> getEntityClass() {
        return entityClass;
    }

    public void setEntityClass(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
    /**
     * 将对象解析为Map
     * @param entity
     * @return
     */
    private Map<String,Object> parse(T entity){
        return op.parse(entity);
    }
}
